package com.zsk.tool.thread;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

public class ShopTest {
    // 测试次数
    public int testIndex = 0;
    // 模拟购买人数
    final int threadNum = 20;
    // 记录购物完毕人数
    AtomicInteger buyFinishNum = new AtomicInteger(0);
    // 商品总数
    int sum = 10000;
    // 已销售总数
    int sellNum = 0;
    // 记录每位购买者购买的商品数
    Map<String, Integer> map = new HashMap<>();

    RedissonClient redissonClient;

    public ShopTest() {
        super();
        initRedisson();
    }

    void initRedisson() {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        redissonClient = Redisson.create(config);
    }

    synchronized void increase(String key, int value) {
        if (map.containsKey(key)) {
            map.put(key, map.get(key) + value);
        } else {
            map.put(key, value);
        }
    }

    public void test(boolean lock) {

        map.clear();
        sellNum = 0;
        buyFinishNum.getAndSet(0);

        for (int i = 0; i < threadNum; i++) {
            new Thread() {
                @Override
                public void run() {
                    if (lock) {
                        RLock lock = redissonClient.getFairLock("test_key");
                        try {
                            boolean hasLock = lock.tryLock(100, 200, TimeUnit.MILLISECONDS);
                            String key = Thread.currentThread().getName();
                            if (hasLock) {
                                while (sellNum < sum) {
                                    sellNum++;
                                    increase(key, 1);
                                }
                                lock.unlock();
                            } else {
                                System.out.println(key + ",系统繁忙...");
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        while (sellNum < sum) {
                            sellNum++;
                            String key = Thread.currentThread().getName();
                            increase(key, 1);
                        }
                    }
                    buyFinishNum.incrementAndGet();
                };
            }.start();
        }
        while (buyFinishNum.get() < threadNum)

        {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        int total = 0;
        for (String key : map.keySet()) {
            int value = map.get(key);
            total += value;
        }
        testIndex++;
        System.out.println("第" + testIndex + "次测试，共卖出" + total + "件" + "," + (total > sum ? "超卖" : "正常"));
    }

    public static void main(String[] args) {
        int testNum = 10;
        ShopTest testLock = new ShopTest();
        System.out.println("加锁测试，20 个人同时购买10000件商品===============");
        for (int i = 0; i < testNum; i++) {
            testLock.test(true);
        }

        System.out.println("不加锁测试，20 个人同时购买10000件商品===============");
        ShopTest testNoneLock = new ShopTest();
        for (int i = 0; i < testNum; i++) {
            testNoneLock.test(false);
        }

    }
}
